package com.example.interview.example.mobileBilling;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;

/**
 * 移动公司
 * 1.在MobileCorporation类内部定义一个List集合的成员变量，用于存储移动公司的所有用户，这里不需要区分普通用户和VIP用户，
 *      而是把他们抽象成用户这个父类，这样就可以采用统一的方式来调用他们各自的行为，普通用户和VIP用户的行为差异，在它们
 *      各自的方法内部体现，这正是充分利用了面向对象的抽象和多态特性。
 * 2.在构造方法中，向用于存储所有用户的List集合中增加15名普通用户和5名VIP用户，每名用户需要有自己的用户名和入网日期。
 * 3.simulationBusiness(Date month)方法来模拟某个月的业务活动，首先清除用户上月的记录信息，
 *      然后再模拟发生如下一些事情：某个用户打电话、某个用户发短信、某个用户传输数据、某个用户订购套餐、某个用户退订套餐、
 *      新用户入网，最后再统计出各个用户在本月的账单信息。模拟发生的事情随机发生，总共模拟发生500次，并让打电话、发短信、
 *      传输数据等事情发生的概率为订购套餐、退订套餐、新用户入网的20倍。
 * 4.将模拟随机发生一件事情的过程封装成一个私有方法randDoOneThing(Date month)，这个方法内部调用的某个用户打电话、某个用户
 *      发短信、某个用户传输数据、某个用户订购套餐、某个用户退订套餐、新用户入网等功能又各自封装成一个私有方法。
 */
public class MobileCorporation {
    private ArrayList<Customer> customers = new ArrayList<Customer>();//存储移动公司的所有用户

    public MobileCorporation() {
        for (int i = 1; i <= 15; i++) { //增加15名普通用户 init入网日期为2008年10月1日
            customers.add(new CommonCustomer(i + "号普通客户", new Date(108, 10, 1)));
        }
        for (int i = 1; i <= 5; i++) {//增加5名VIP用户
            customers.add(new VIPCustomer(i + "号VIP客户", new Date(108, 10, 1)));
        }
        System.out.println("程序创建了运营商已有的5个VIP用户和15个普通用户，并设置他们的入网日期为2008年10月1日.");
    }

    //模拟某个月的业务活动 （模拟一个月的业务，内部随机做500件事情和结算每个用户的计费情况，随机做的事情就是挑选一个用户做其中
    // 任何一件事情：打电话/发短信/数据通信/定套餐/退订套餐/新用户入网）
    public void simulationBusiness(Date month) {
        for (Customer customer : customers) {
            customer.monthBegin(); //首先清除用户上月的记录信息
        }
        System.out.println("--------being simulating " + DateUtil.formatDateToMonth(month) + "--------------");
        for (int i = 0; i < 500/*30*/; i++) { //打电话、发短信、传输数据、订购套餐、退订套餐、新用户入网 随机发生500次
            randDoOneThing(month); //随机调用500次通讯业务方法(随机生成打电话、发短信、流量的使用量化数据)
        }

        System.out.println(DateUtil.formatDateToMonth(month) + "的计费汇总清单：");
        //汇总所有人的账单
        for (int i = 0; i < customers.size(); i++) {
            customers.get(i).countMonthMoney(month);
        }

    }

    /**
     * 模拟随机调用通讯业务(随机生成打电话、发短信、流量的使用量化数据)
     */
    private void randDoOneThing(Date month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(month);
        calendar.add(Calendar.MONTH, 1);    //订购、退订套餐 下月生效! 用户可自由订制或退订所属用户类型的套餐，并从下月起生效
        Date monthOfOrderPack = calendar.getTime();  //订购、退订套餐下月生效!
        //打电话、发短信、传输数据等事情发生的概率是orderPack、cancelPack、joinNewCustomer的20倍。
        int rand = new Random().nextInt(63);
        if (rand >= 0 && rand < 20) {
            callPhone();//打电话
        } else if (rand >= 20 && rand < 40) {
            sendMessage();//发短信
        } else if (rand >= 40 && rand < 60) {
            transferData();//流量
        } else { //20 : 20 : 20 : 1 : 1 : 1
            switch (rand) {
                case 60:
                    orderPack(monthOfOrderPack);//订购套餐
                    break;
                case 61:
                    cancelPack(monthOfOrderPack);//退订套餐
                    break;
                case 62:
                    joinNewCustomer(month);//新用户入网
                    break;
            }
        }
    }

    /**
     * 随机选中一个用户，让其随机拨打的电话时长为1至10分钟不等
     */
    private void callPhone() {
        int rand = new Random().nextInt(customers.size());
        Customer customer = customers.get(rand);
        int phoneTimes = new Random().nextInt(10) + 1;
        customer.callPhone(phoneTimes);
        System.out.println(customer + "打了" + phoneTimes + "分钟电话");
    }

    /**
     * 随机选中一个用户，让其随机发送的短信数目为1至10条不等
     */
    private void sendMessage() {
        int rand = new Random().nextInt(customers.size());
        Customer customer = customers.get(rand);
        int messageNumbers = new Random().nextInt(10) + 1;
        customer.sendMessage(messageNumbers);
        System.out.println(customer + "发了" + messageNumbers + "条短信");
    }

    /**
     * 随机选中一个用户，让其随机获取的数据流量为50K，100K，200K，500K，1M
     */
    private void transferData() {
        int rand = new Random().nextInt(customers.size());
        Customer customer = customers.get(rand);

        int[] dataSize = new int[]{50, 100, 200, 500, 1000};
        int randSizeKey = new Random().nextInt(5);
        customer.transferData(dataSize[randSizeKey]);
        System.out.println(customer + "传送了" + dataSize[randSizeKey] + "k数据");
    }

    /**
     * 随机选中一个用户，为其随机订购一款套餐
     */
    private void orderPack(Date month) {
        int rand = new Random().nextInt(customers.size());
        customers.get(rand).randomOrderPack(month); // 待看1
    }

    /**
     * 随机选中一个用户，并将其已经有的套餐取消
     */
    private void cancelPack(Date month) {
        int rand = new Random().nextInt(customers.size());
        customers.get(rand).randomCancelPack(month);
    }

    private void joinNewCustomer(Date month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(month);
        int maxDay = calendar.getMaximum(Calendar.DAY_OF_MONTH);
        int randDay = new Random().nextInt(maxDay) + 1;
        /*下面的复制过程很重要，不能直接修改date，当然最好是对Calendar直接操作
         * 这里是为了演示要注意clone而保留的。
         */
        Date joinTime = (Date) month.clone();
        joinTime.setDate(randDay);

        int randType = (new Random().nextInt(10)) % 2;
        Customer customer = null;
        if (randType == 0) {
            int commonId = IdGenerator.getInstance().nextCommonId();
            customer = new CommonCustomer(commonId + "号普通客户", joinTime);
            customers.add(customer);
        } else {
            int vipId = IdGenerator.getInstance().nextVipId();
            customer = new VIPCustomer(vipId + "号VIP客户", joinTime);
            customers.add(customer);
        }
        System.out.println(DateUtil.formatDateToDay(joinTime) + "新注册了" + customer);
    }

}
